home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: ocat.r -- caterr, lconcat
- */
- "x || y - concatenate strings x and y."
-
- operator{1} || cater(x, y)
-
- if !cnv:string(x) then
- runerr(103, x)
- if !cnv:string(y) then
- runerr(103, y)
-
- abstract {
- return string
- }
-
- body {
- /*
- * Optimization 1: The strings to be concatenated are already
- * adjacent in memory; no allocation is required.
- */
- if (StrLoc(x) + StrLen(x) == StrLoc(y)) {
- StrLoc(result) = StrLoc(x);
- StrLen(result) = StrLen(x) + StrLen(y);
- return result;
- }
- #ifdef MultiRegion
- else if ((StrLoc(x) + StrLen(x) == strfree) && (DiffPtrs(strend,strfree) > StrLen(y))) {
- #else /* MultiRegion */
- else if (StrLoc(x) + StrLen(x) == strfree) {
- #endif /* MultiRegion */
- /*
- * Optimization 2: The end of x is at the end of the string space.
- * Hence, x was the last string allocated and need not be
- * re-allocated. y is appended to the string space and the
- * result is pointed to the start of x.
- */
- result = x;
- }
- else {
- /*
- * Otherwise, append x to the end of the string space and
- * point the result to the start of y.
- */
- Protect(StrLoc(result) = alcstr(StrLoc(x),StrLen(x)), runerr(0));
- StrLen(result) = StrLen(x);
- }
-
- /*
- * Append y to the end of the string space.
- */
- Protect(alcstr(StrLoc(y),StrLen(y)), runerr(0));
- /*
- * Set the length of the result and return.
- */
- StrLen(result) = StrLen(x) + StrLen(y);
- return result;
- }
- end
-
-
- "x ||| y - concatenate lists x and y."
-
- operator{1} ||| lconcat(x, y)
- /*
- * x and y must be lists.
- */
- if !is:list(x) then
- runerr(108, x)
- if !is:list(y) then
- runerr(108, y)
-
- abstract {
- return new list(store[(type(x) ++ type(y)).lst_elem])
- }
-
- body {
- register struct b_list *bp1, *bp2;
- register struct b_lelem *lp1, *lp2;
- word size1, size2;
-
- /*
- * Get the size of both lists.
- */
- size1 = BlkLoc(x)->list.size;
- size2 = BlkLoc(y)->list.size;
-
- /*
- * Make a copy of both lists.
- */
- if (cplist(&x, &x, (word)1, size1 + 1) == Error)
- runerr(0);
- if (cplist(&y, &y, (word)1, size2 + 1) == Error)
- runerr(0);
-
- /*
- * Get a pointer to both lists. bp1 points to the copy of x
- * and is the list that will be returned.
- */
- bp1 = (struct b_list *) BlkLoc(x);
- bp2 = (struct b_list *) BlkLoc(y);
-
- /*
- * Perform the concatenation by hooking the lists together.
- */
- lp1 = (struct b_lelem *) bp1->listtail;
- lp2 = (struct b_lelem *) bp2->listhead;
-
- lp1->listnext = (union block *) lp2;
- lp2->listprev = (union block *) lp1;
-
- /*
- * Adjust the size field to reflect the length of the concatenated lists.
- */
- bp1->size = size1 + size2;
- bp1->listtail = bp2->listtail;
-
- return x;
- }
- end
-